﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Ewk.MachineLearning.Genetic.Programming.Program.Functions
{
    public class Function : IFunctionDefinition
    {
        readonly string _readable;

        public Function(Func<IEnumerable<dynamic>, dynamic> value, IEnumerable<IODefinition> inputDefinitions, IODefinition outputDefinition)
            : this(value, inputDefinitions, outputDefinition, null)
        {
        }

        public Function(Func<IEnumerable<dynamic>, dynamic> value, IEnumerable<IODefinition> inputDefinitions, IODefinition outputDefinition, string readable)
        {
            Value = value;
            InputDefinitions = inputDefinitions;
            OutputDefinition = outputDefinition;

            _readable = readable ?? string.Empty;
        }

        #region Implementation of IFunctionDefinition

        /// <summary>
        /// Gets the arity of the function.
        /// </summary>
        /// <remarks>The number of parameters the function takes, is called its arity.</remarks>
        public int Arity
        {
            get { return InputDefinitions.Count(); }
        }

        /// <summary>
        /// Gets the <see cref="IODefinition"/> of this function.
        /// </summary>
        public IEnumerable<IODefinition> InputDefinitions { get; private set; }

        /// <summary>
        /// Gets the <see cref="IODefinition"/> of this function.
        /// </summary>
        public IODefinition OutputDefinition { get; private set; }

        #endregion

        /// <summary>
        /// The function that is used to transform the parameters.
        /// </summary>
        internal Func<IEnumerable<dynamic>, dynamic> Value { get; private set; }

        /// <summary>
        /// Gets the string representation of this function.
        /// </summary>
        /// <returns>A readable string that represents this function.</returns>
        public override string ToString()
        {
            return _readable;
        }
    }
}